package com.outsider.util;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.SecureRandom;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.TimeUnit;

import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;

import com.jfinal.kit.StrKit;
import com.jfinal.weixin.sdk.api.MediaFile;
import com.jfinal.weixin.sdk.utils.IOUtils;

public class OkHttp3 {
    private okhttp3.OkHttpClient httpClient;
    private static OkHttp3 instance=null;
    public static OkHttp3 getInstance(){
    	if (instance==null){
    		synchronized (OkHttp3.class) {
    		  if (instance==null)
    			  instance=new OkHttp3();
    		}
    	}
    	return instance;
    }
    private OkHttp3() {
        // 分别设置Http的连接,写入,读取的超时时间
        httpClient = new okhttp3.OkHttpClient().newBuilder()
                .connectTimeout(10, TimeUnit.SECONDS)
                .writeTimeout(10, TimeUnit.SECONDS)
                .readTimeout(30, TimeUnit.SECONDS)
                .build();
    }

    private static final okhttp3.MediaType CONTENT_TYPE_FORM =
            okhttp3.MediaType.parse("application/x-www-form-urlencoded");

    private String exec(okhttp3.Request request) {
        try {
            okhttp3.Response response = httpClient.newCall(request).execute();

            if (!response.isSuccessful()) throw new RuntimeException("Unexpected code " + response);

            return response.body().string();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }


    public String get(String url) {
        okhttp3.Request request = new okhttp3.Request.Builder().url(url).get().build();
        return exec(request);
    }

//    public String get(String url,String authorization){
//    	 okhttp3.Request request = new okhttp3.Request.Builder().addHeader("Authorization", authorization).url(url).get().build();
//    	 return exec(request);
//    }
    
    public String getWithHeader(String url,Map<String, String> header){
    	okhttp3.Request.Builder builder = new okhttp3.Request.Builder();
        for (Entry<String, String> entry : header.entrySet()) {
        	builder.addHeader(entry.getKey(), entry.getValue());
        }
        okhttp3.Request request = builder.url(url).get().build();
        return exec(request);
    }
    
    public String get(String url, Map<String, String> queryParas) {
        okhttp3.HttpUrl.Builder urlBuilder = okhttp3.HttpUrl.parse(url).newBuilder();
        for (Entry<String, String> entry : queryParas.entrySet()) {
            urlBuilder.addQueryParameter(entry.getKey(), entry.getValue());
        }
        okhttp3.HttpUrl httpUrl = urlBuilder.build();
        okhttp3.Request request = new okhttp3.Request.Builder().url(httpUrl).get().build();
        return exec(request);
    }


    public String post(String url, String params) {
        okhttp3.RequestBody body = okhttp3.RequestBody.create(CONTENT_TYPE_FORM, params);
        okhttp3.Request request = new okhttp3.Request.Builder()
            .url(url)
            .post(body)
            .build();
        return exec(request);
    }


    public String postSSL(String url, String data, String certPath, String certPass) {
        okhttp3.RequestBody body = okhttp3.RequestBody.create(CONTENT_TYPE_FORM, data);
        okhttp3.Request request = new okhttp3.Request.Builder()
            .url(url)
            .post(body)
            .build();

        InputStream inputStream = null;
        try {
            KeyStore clientStore = KeyStore.getInstance("PKCS12");
            inputStream = new FileInputStream(certPath);
            char[] passArray = certPass.toCharArray();
            clientStore.load(inputStream, passArray);

            KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
            kmf.init(clientStore, passArray);
            KeyManager[] kms = kmf.getKeyManagers();
            SSLContext sslContext = SSLContext.getInstance("TLSv1");

            sslContext.init(kms, null, new SecureRandom());

            okhttp3.OkHttpClient httpsClient = new okhttp3.OkHttpClient()
                    .newBuilder()
                    .connectTimeout(10, TimeUnit.SECONDS)
                    .writeTimeout(10, TimeUnit.SECONDS)
                    .readTimeout(30, TimeUnit.SECONDS)
                    .sslSocketFactory(sslContext.getSocketFactory())
                    .build();

            okhttp3.Response response = httpsClient.newCall(request).execute();

            if (!response.isSuccessful()) throw new RuntimeException("Unexpected code " + response);

            return response.body().string();
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            IOUtils.closeQuietly(inputStream);
        }
    }


    public MediaFile download(String url) {
        okhttp3.Request request = new okhttp3.Request.Builder().url(url).get().build();
        try {
            okhttp3.Response response = httpClient.newCall(request).execute();

            if (!response.isSuccessful()) throw new RuntimeException("Unexpected code " + response);

            okhttp3.ResponseBody body = response.body();
            okhttp3.MediaType mediaType = body.contentType();
            MediaFile mediaFile = new MediaFile();
            if (mediaType.type().equals("text")) {
                    mediaFile.setError(body.string());
            } else {
                BufferedInputStream bis = new BufferedInputStream(body.byteStream());

/*                    String ds = response.header("Content-disposition");
                String fullName = ds.substring(ds.indexOf("filename=\"") + 10, ds.length() - 1);
                String relName = fullName.substring(0, fullName.lastIndexOf("."));
                String suffix = fullName.substring(relName.length()+1);

                mediaFile.setFullName(fullName);
                mediaFile.setFileName(relName);
                mediaFile.setSuffix(suffix);
                mediaFile.setContentLength(body.contentLength() + "");
                mediaFile.setContentType(body.contentType().toString());*/
                mediaFile.setFileStream(bis);
            }
            return mediaFile;
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }


    public InputStream download(String url, String params) {
        okhttp3.Request request;
        if (StrKit.notBlank(params)) {
            okhttp3.RequestBody body = okhttp3.RequestBody.create(CONTENT_TYPE_FORM, params);
            request = new okhttp3.Request.Builder().url(url).post(body).build();
        } else {
            request = new okhttp3.Request.Builder().url(url).get().build();
        }
        try {
            okhttp3.Response response = httpClient.newCall(request).execute();

            if (!response.isSuccessful()) throw new RuntimeException("Unexpected code " + response);

            return response.body().byteStream();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }


    public String upload(String url, File file, String params) {
        okhttp3.RequestBody fileBody = okhttp3.RequestBody
                .create(okhttp3.MediaType.parse("application/octet-stream"), file);

        okhttp3.MultipartBody.Builder builder = new okhttp3.MultipartBody.Builder()
                .setType(okhttp3.MultipartBody.FORM)
                .addFormDataPart("media", file.getName(), fileBody);

        if (StrKit.notBlank(params)) {
            builder.addFormDataPart("description", params);
        }

        okhttp3.RequestBody requestBody = builder.build();
        okhttp3.Request request = new okhttp3.Request.Builder()
                .url(url)
                .post(requestBody)
                .build();

        return exec(request);
    }

}